home *** CD-ROM | disk | FTP | other *** search
/ TPUG - Toronto PET Users Group / TPUG Users Group CD / TPUG Users Group CD.iso / CRS / crs55.d81 / cdi.c < prev    next >
Text File  |  2009-10-10  |  5KB  |  264 lines

  1. /*
  2.  * CDI.C - CHARACTER DIFFERENCE DETECTOR
  3.  *
  4.  * ┴DRIAN ╨EPPER, 1987
  5.  *
  6.  * DEVELOPED WITH/FOR ├ ╨╧╫┼╥ 64 SYSTEM
  7.  *
  8.  * ╒PLOADED AS IS, IN RESPONSE TO
  9.  * PERCEIVED NEED.  (╘HAT'S AN APOLOGY
  10.  * FOR LACK OF COMMENTS)
  11.  *
  12.  * ╒SAGE:
  13.  *
  14.  * CDI [-H -O# -L# -M#] FILE1 FILE2
  15.  *
  16.  *  -H GIVE OUTPUT IN HEX (ELSE DECIMAL)
  17.  *
  18.  *  -O SPECIFY AN OFFSET (IN DECIMAL) TO
  19.  *     BE ASSUMED FOR BEGINNING OF FILE
  20.  *
  21.  *  -L,-M SET VALUES OF VARS MATLEN,
  22.  *     AND MATRAT, WHICH INFLUENCE THE
  23.  *     ALGORITHM FOR DECIDING WHEN FILES
  24.  *     ARE MATCHING AGAIN
  25.  */
  26. #INCLUDE <STDIO.H>
  27.  
  28. #DEFINE ┘┼╙ 1
  29. #DEFINE ╬╧ 0
  30.  
  31. TYPEDEF INT ┬╔╟;   /* USE FLOAT FOR REALLY ┬╔╟ FILES */
  32.  
  33. INT MATLEN = 20;
  34. INT MATRAT = 2;
  35. INT HEX = 0;
  36. INT OFFSET = 0;
  37. MAIN(ARGC,AV)
  38. INT ARGC;
  39. CHAR **AV;
  40.   AUTO ╞╔╠┼ F1, F2;
  41.   AUTO CHAR **ARGV;
  42.  
  43.   ARGV = AV;
  44.   ARGC = OPTION(ARGC, &ARGV);
  45.   IF (ARGC < 2) █
  46.     PRINTF("USAGE:CDI [-L# -M# -H -O#] FILE1 FILE2\N");
  47.     EXIT(1);
  48.   ▌
  49.   IF ((F1 = FOPEN(ARGV[0], "R")) == 0 ▀▀
  50.     FERROR()) █
  51.     PRINTF("CAN'T OPEN %S\N",ARGV[0]);
  52.     EXIT(1);
  53.   ▌
  54.   IF ((F2 = FOPEN(ARGV[1], "R")) == 0 ▀▀
  55.     FERROR()) █
  56.     PRINTF("CAN'T OPEN %S\N",ARGV[1]);
  57.     EXIT(1);
  58.   ▌
  59.   CDI(F1, F2, ARGV[0], ARGV[1]);
  60.  
  61. OPTION(ARGC, PARGV)
  62. INT ARGC;
  63. CHAR ***PARGV;
  64.   AUTO CHAR **ARGV;
  65.  
  66.   MATLEN = 20;
  67.   MATRAT = 2;
  68.   HEX = 0;
  69.   OFFSET = 0;
  70.  
  71.   ARGV = *PARGV;
  72.   ++ARGV;
  73.   --ARGC;
  74.   WHILE (ARGC > 0 && *ARGV[0] == '-') █
  75.     SWITCH ((*ARGV)[1])
  76.     █
  77.     CASE 'L':
  78.       IF (--ARGC < 1 ▀▀ (MATLEN = ATOI(*++ARGV)) <= 0)
  79.         MATLEN = 1;
  80.       BREAK;
  81.     CASE 'M':
  82.       IF (--ARGC < 1 ▀▀ (MATRAT = ATOI(*++ARGV)) <= 0)
  83.         MATRAT = 1;
  84.       BREAK;
  85.     CASE 'O':
  86.       IF (--ARGC >= 1)
  87.         OFFSET = ATOI(*++ARGV);
  88.       BREAK;
  89.     CASE 'H':
  90.       HEX = 1;
  91.       BREAK;
  92.     DEFAULT:
  93.       *PARGV = ARGV;
  94.       RETURN 0; 
  95.     ▌ 
  96.     --ARGC;
  97.     ++ARGV;
  98.   ▌
  99.   *PARGV = ARGV;
  100.   RETURN ARGC;
  101.  
  102.  
  103. BCMP(B1, B2, LEN)
  104. INT B1[], B2[];
  105. INT LEN;
  106.   AUTO INT I;
  107.  
  108.   FOR (I = 0; I < LEN; ++I)
  109.     IF (B1[I] != B2[I]) RETURN ╬╧;
  110.   RETURN ┘┼╙;
  111.  
  112. MATCH(U1, B1, R1, U2, B2, R2, LENGTH)
  113. INT U1;
  114. INT B1[];
  115. INT R1;
  116. INT U2;
  117. INT B2[];
  118. INT R2;
  119. INT LENGTH;
  120.   AUTO INT I;
  121.  
  122.   IF ((R1-U1) < LENGTH ▀▀ (R2-U2) < LENGTH) RETURN R1;
  123.   FOR (I = U1; I <= (R1-LENGTH) && BCMP(&B1[I], &B2[R2-LENGTH], LENGTH) == ╬╧; ++I)
  124.     ;
  125.   RETURN I;
  126.  
  127. SHUFFLE(BUF, R, U)
  128. INT BUF[];
  129. INT R, U;
  130.   AUTO INT I;
  131.  
  132.   IF (U == 0) █
  133.     PRINTF("╘OO MANY DIFFERENCES\N");
  134.     EXIT(1);
  135.   ▌
  136.   FOR (I = U; I < R; ++I)
  137.     BUF[I-U] = BUF[I];
  138.   RETURN R-U;
  139.  
  140.  
  141. #DEFINE ═┴╪┬╒╞ 1000
  142. INT BUF1[═┴╪┬╒╞] = █0▌;
  143. INT BUF2[═┴╪┬╒╞] = █0▌;
  144. CDI(F1, F2, NAME1, NAME2)
  145. ╞╔╠┼ F1, F2;
  146. CHAR *NAME1, *NAME2;
  147.   AUTO ┬╔╟ COUNT1, COUNT2;
  148.   AUTO INT USED1, USED2;  /* BUFFERED CHAR "USED" */
  149.   AUTO INT READ1, READ2;  /* BUFFERED CHAR "READ" */
  150.   AUTO INT I1, I2;
  151.   AUTO INT LEN;
  152.   AUTO CHAR *FMT;
  153.  
  154.   READ1 = READ2 = 0;
  155.   USED1 = USED2 = 0;
  156.   COUNT1 = COUNT2 = ((┬╔╟)OFFSET);
  157.  
  158.   FOR ( ; ; ) █
  159.     WHILE (USED1 != READ1 ▀▀ USED2 != READ2) █
  160.       IF (USED1 == READ1) █
  161.         USED1 = READ1 = 0;
  162.         BUF1[READ1++] = GETC(F1);
  163.       ▌
  164.       IF (USED2 == READ2) █
  165.         USED2 = READ2 = 0;
  166.         BUF2[READ2++] = GETC(F2);
  167.       ▌
  168.       LEN = READ1-USED1;
  169.       IF ((READ2-USED2) > LEN) LEN = READ2-USED2;
  170.       LEN = (LEN/MATRAT) + 1;
  171.       IF (LEN > MATLEN) LEN = MATLEN;
  172.       I1 = MATCH(USED1, BUF1, READ1, USED2, BUF2, READ2, LEN);
  173.       I2 = MATCH(USED2, BUF2, READ2, USED1, BUF1, READ1, LEN);
  174.       /* ASSERT USED1 < READ1 && USED2 < READ2 */
  175.       IF (BUF1[USED1] == BUF2[USED2]) █
  176.         ++USED1;
  177.         ++USED2;
  178.         COUNT1 = COUNT1 + ((┬╔╟)1);
  179.         COUNT2 = COUNT2 + ((┬╔╟)1);
  180.       ▌
  181.       ELSE IF (I1 <= (READ1-LEN) && (I2 > (READ2-LEN) ▀▀ (I1-USED1) <= (I2-USED2))) █
  182.         SHOWDIFF(&COUNT1, BUF1, &USED1, I1, &COUNT2, BUF2, &USED2, READ2-LEN, LEN);
  183.       ▌
  184.       ELSE IF (I2 <= (READ2-LEN) && (I1 > (READ1-LEN) ▀▀ (I2-USED2) <= (I1-USED1))) █
  185.         SHOWDIFF(&COUNT1, BUF1, &USED1, READ1-LEN, &COUNT2, BUF2, &USED2, I2, LEN);
  186.       ▌
  187.       ELSE █
  188.         IF (READ1 >= ═┴╪┬╒╞) █
  189.           READ1 = SHUFFLE(BUF1, READ1, USED1);
  190.           USED1 = 0;
  191.         ▌
  192.         BUF1[READ1++] = GETC(F1);
  193.         IF (READ2 >= ═┴╪┬╒╞) █
  194.           READ2 = SHUFFLE(BUF2, READ2, USED2);
  195.           USED2 = 0;
  196.         ▌
  197.         BUF2[READ2++] = GETC(F2);
  198.       ▌
  199.     ▌
  200.     USED1 = READ1 = 0;
  201.     BUF1[0] = GETC(F1);
  202.     USED2 = READ2 = 0;
  203.     BUF2[0] = GETC(F2);
  204.     IF (BUF1[0] == ┼╧╞ && BUF2[0] == ┼╧╞) BREAK;
  205.     IF (BUF1[0] != BUF2[0]) █
  206.       ++READ1;
  207.       ++READ2;
  208.     ▌
  209.     ELSE █
  210.       COUNT1 = COUNT1 + ((┬╔╟)1);
  211.       COUNT2 = COUNT2 + ((┬╔╟)1);
  212.     ▌
  213.   ▌
  214.   FMT = "%D:%S %0.0F(%0.0F BYTES)\N";
  215.   IF (SIZEOF(┬╔╟) != SIZEOF(FLOAT))
  216.     FMT = HEX ? "%D:%S $%04X (%D BYTES)\N" : "%D:%S %D (%D BYTES)\N";
  217.   PRINTF(FMT, 1, NAME1, COUNT1, COUNT1-((┬╔╟)OFFSET));
  218.   PRINTF(FMT, 2, NAME2, COUNT2, COUNT2-((┬╔╟)OFFSET));
  219.  
  220. SHOWDIFF(PC1, B1, PU1, I1, PC2, B2, PU2, I2, LEN)
  221. ┬╔╟ *PC1;
  222. INT B1[];
  223. INT *PU1;
  224. INT I1;
  225. ┬╔╟ *PC2;
  226. INT B2[];
  227. INT *PU2;
  228. INT I2;
  229.   AUTO INT I;
  230.   AUTO CHAR *FMT;
  231.  
  232.   FMT = "%D:(%6.0F):";
  233.   IF (SIZEOF(┬╔╟) != SIZEOF(FLOAT))
  234.     FMT = HEX ? "%D:($%04X):" : "%D:(%6D):";
  235.   IF (B1[I1+LEN-1] != B2[I2+LEN-1]) █
  236.     PRINTF("SHOULDN'T HAPPEN\N");
  237.   ▌
  238.   PRINTF(FMT, 1, *PC1);
  239.   FOR (I = *PU1; I <= I1; ++I)
  240.     PRINTF(" %02X", B1[I]);
  241.   PRINTF("\N");
  242.   PRINTF(FMT, 2, *PC2);
  243.   FOR (I = *PU2; I <= I2; ++I)
  244.     PRINTF(" %02X", B2[I]);
  245.   PRINTF("\N");
  246.   *PC1 = *PC1 + ((┬╔╟)(I1 - *PU1 + 1));
  247.   *PU1 = I1 + 1;
  248.   *PC2 = *PC2 + ((┬╔╟)(I2 - *PU2 + 1));
  249.   *PU2 = I2 + 1;